#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>

#define NUM 1024
#define SIZE 32


char cmd_line[NUM];//保存完整的命令语句
char *g_argv[SIZE];//保存打散之后的命令行字符串


int main()
{
  //0.命令行解释器是一个永远不退出的程序
  while(1)
  {
    //1.打印提示符
    printf("[violet@VM-4-16-centos my_shell]# ");
    //2.存储用户输入的命令
    memset(cmd_line, '\0', sizeof cmd_line);
    while(fgets(cmd_line, sizeof cmd_line, stdin) == NULL)
    {
      continue;
    }
    cmd_line[strlen(cmd_line) - 1] = '\0';//去除字符串最后存储的回车
    //3.命令行字符串解析-->存在数组中的是一整串字符串，将它分为不同部分
    g_argv[0] = strtok(cmd_line, " ");
    int index = 1;

    if(strcmp(g_argv[0], "ls") == 0)
    {
      g_argv[index++] = "--color=auto";
    }

    if(strcmp(g_argv[0], "ll") == 0)
    {
      g_argv[0] = "ls";
      g_argv[index++] = "-l";
      g_argv[index++] = "--color=auto";
    }

    while(g_argv[index++] = strtok(NULL, " "));
    
    //4.内置命令-->有的命令我们需要让父进程自己执行，如果让子进程执行无法达到想要的效果，例如cd如果让子进程执行，那么在子进程退出后父进程依旧在原来的目录下
    if(strcmp(g_argv[0], "cd") == 0)
    {
      if(g_argv[1] != NULL) chdir(g_argv[1]); 
    }

    //5.创建子进程，执行命令
    id_t id = fork();
    if(id < 0)
    {
      printf("子进程创建失败！\n");
      continue;
    }
    else if(id == 0)
    {
      printf("子进程正在执行任务\n!");
      execvp(g_argv[0], g_argv);
      exit(-1);
    }

    int status = 0;
    id_t pid = waitpid(-1, &status, 0);
    if(pid > 0) 
      printf("退出码：%d\n", WEXITSTATUS(status));

  }
}
